package com.orange.api;

import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.Cookie;
import org.eclipse.jetty.http.HttpStatus;
import server.IHandleSessionManager;
import server.rest.ContentType;
import server.rest.HttpContext;
import server.rest.HttpMethod;
import server.rest.ResponseException;
import server.rest.Rest;
import server.rest.SessionType;
import server.rest.sessions.SessionManagerController;
import annotation.Inject;
import com.orange.api.dto.BOUserDto;
import common.BaseUtils;
import common.ConfigHelper;

public class AuthHandler
{
    @Inject(type = server.IHandleSessionManager.class)
    SessionManagerController<String, Long, UserSession> sessionManagerController;
    final static String cookieKey = ConfigHelper.getStringProperty("server.session.cookieKey", "sessionId");

    @Rest(method = HttpMethod.GET, schema = "/uid", internal = false, responseContentType = ContentType.JSON)
    public String doGetUUID(HttpContext context)
    {
        return createUserToken(context);
    }

    private String createUserToken(HttpContext context)
    {
        return BaseUtils.encodeForBase64(String.format("%s-%s-%s", context.getRequest().getRemoteAddr(),
            context.getRequest().getRequestedSessionId(),
            context.getRequest().getHeader("User-Agent")));
    }

    Map<String, BOUserDto> userMap = new HashMap<String, BOUserDto>();
    java.util.concurrent.atomic.AtomicLong index = new java.util.concurrent.atomic.AtomicLong(
                    System.currentTimeMillis());

    @Rest(method = HttpMethod.GET, schema = "/register/name/(name)", internal = false, requestContentType = ContentType.JSON)
    public void doCheckUserName(HttpContext context, BOUserDto user) throws ResponseException
    {
        String name = context.getParameter("name");
        if (userMap.containsKey(name))
        {
            throw new ResponseException(HttpStatus.FORBIDDEN_403, "The user name already exist.");
        }
        // TODO verify other property.
        if (!verifyUser(user))
        {
            throw new ResponseException(HttpStatus.FORBIDDEN_403, "Verify failed.");
        }
    }

    private boolean verifyUser(BOUserDto user)
    {
        return true;
    }

    @Rest(method = HttpMethod.POST, schema = "/register", internal = false, requestContentType = ContentType.JSON, responseContentType = ContentType.JSON)
    public String doPostRegister(HttpContext context, BOUserDto user) throws ResponseException
    {
        if (!verifyUser(user))
        {
            throw new ResponseException(HttpStatus.FORBIDDEN_403, "Verify failed.");
        }

        createSystemUser(user);

        user.setToken(createUserToken(context));

        UserSession tempSession = new UserSession(user.getToken(), index.incrementAndGet());
        sessionManagerController.add(tempSession);
        System.out.println(cookieKey + " : " + tempSession.getKey());
        context.getResponse().addCookie(new Cookie(cookieKey, tempSession.getKey()));
        return "Register Success";
    }

    private void createSystemUser(BOUserDto user)
    {
        System.out.println(user.getUserName() + " : " + user.getPassword());
        user.setPassword(user.getPassword());
        userMap.put(user.getUserName(), user);
    }

    @Rest(method = HttpMethod.POST, schema = "/bo/login", internal = false, sessionType = SessionType.SESSION, responseContentType = ContentType.JSON, requestContentType = ContentType.JSON)
    public String dologin(HttpContext context, UserSession tempSesion, BOUserDto user) throws ResponseException
    {
        String name = user.getUserName();
        if (!userMap.containsKey(name))
        {
            throw new ResponseException(HttpStatus.FORBIDDEN_403, "The user name isn't exist.");
        }

        BOUserDto savedUser = userMap.get(name);
        String currentlyUserToken = createUserToken(context);

        String savedUserPwd =
                        BaseUtils.encryptForMD5(String.format("%s|%s_%s", currentlyUserToken, name,
                            savedUser.getPassword()));

        System.out.println(savedUserPwd);
        System.out.println(user.getPassword());
        if (savedUserPwd.equals(user.getPassword()))
        {
            Long temporaryId = null;
            if (null != tempSesion)
            {
                temporaryId = tempSesion.getId();
            }
            else
            {
                temporaryId = index.get();
            }

            UserSession userSession =
                            new UserSession(BaseUtils.encryptForMD5(String.format("%s|%s", savedUserPwd,
                                temporaryId)), getSystemUserIdByUserName(name));

            sessionManagerController.add(userSession);
            context.getResponse().addCookie(new Cookie(cookieKey, userSession.getKey()));

            if (tempSesion != null && currentlyUserToken.equals(tempSesion.getKey()))
            {
                // remove the temporary session
                sessionManagerController.remove(tempSesion);
            }
            else
            {
                sessionManagerController.remove(currentlyUserToken);
            }

            return "success";
        }

        if (!currentlyUserToken.equals(savedUser.getToken()))
        {

            throw new ResponseException(HttpStatus.FORBIDDEN_403, "Password Incorrect");
        }

        throw new ResponseException(HttpStatus.BAD_REQUEST_400, "Password Incorrect");
    }

    @Rest(method = HttpMethod.POST, schema = "/bo/logout", internal = false, requestContentType = ContentType.JSON, sessionType = SessionType.SESSION)
    public void dologout(HttpContext context, UserSession session) throws ResponseException
    {
        if (session != null)
        {
            String name = getSystemUserName(session.getId());
            if (userMap.containsKey(name))
            {
                userMap.remove(name);
            }

        }
        else
        {
            throw new ResponseException(HttpStatus.NOT_FOUND_404, "currently session already removed.");
        }

    }

    private String getSystemUserName(Long id)
    {
        return "test";
    }

    private long getSystemUserIdByUserName(String userName)
    {
        return 10000L;
    }

    public void setSessionManagerController(IHandleSessionManager<String, Long, UserSession> provider)
    {
        if (null != provider)
        {
            this.sessionManagerController = provider.getSessionManager();
        }
    }
}
